home *** CD-ROM | disk | FTP | other *** search
/ Linux Cubed Series 7: Sunsite / Linux Cubed Series 7 - Sunsite Vol 1.iso / system / network / admin / xinetd.2 / xinetd / xinetd.2.1.7-linux.4 / libs / src / sio / sprint.c < prev   
Encoding:
C/C++ Source or Header  |  1995-09-10  |  17.3 KB  |  768 lines

  1. /*
  2.  * (c) Copyright 1992, 1993 by Panagiotis Tsirigotis
  3.  * All rights reserved.  The file named COPYRIGHT specifies the terms 
  4.  * and conditions for redistribution.
  5.  */
  6.  
  7.  
  8. static char RCSid[] = "$Id: sprint.c,v 1.5 1995/09/10 18:35:09 chuck Exp $" ;
  9.  
  10. #include <ctype.h>
  11. #include <sys/param.h>
  12.  
  13. #include "sio.h"
  14. #include "impl.h"
  15.  
  16. #ifndef WIDE_INT
  17. #define WIDE_INT                            long
  18. #endif
  19.  
  20. typedef WIDE_INT                             wide_int ;
  21. typedef unsigned WIDE_INT                 u_wide_int ;
  22. typedef int                                 bool_int ;
  23.  
  24. #define S_NULL                                "(null)"
  25. #define S_NULL_LEN                        6
  26.  
  27. #define FLOAT_DIGITS                        6
  28. #define EXPONENT_LENGTH                    10
  29.  
  30. /*
  31.  * NUM_BUF_SIZE is the size of the buffer used for arithmetic conversions
  32.  *
  33.  * XXX: this is a magic number; do not decrease it
  34.  */
  35. #define NUM_BUF_SIZE                        512
  36.  
  37. /*
  38.  * The INS_CHAR macro inserts a character in the buffer and writes
  39.  * the buffer back to disk if necessary
  40.  * It uses the char pointers sp and bep:
  41.  *     sp points to the next available character in the buffer
  42.  *     bep points to the end-of-buffer+1
  43.  * While using this macro, note that the nextb pointer is NOT updated.
  44.  *
  45.  * No I/O is performed if fd is not positive. Negative fd values imply
  46.  * conversion with the output directed to a string. Excess characters
  47.  * are discarded if the string overflows.
  48.  *
  49.  * NOTE: Evaluation of the c argument should not have any side-effects
  50.  */
  51. #define INS_CHAR( c, sp, bep, odp, cc, fd )                                            \
  52.             {                                                                                        \
  53.                 if ( sp < bep )                                                                \
  54.                 {                                                                                    \
  55.                     *sp++ = c ;                                                                    \
  56.                     cc++ ;                                                                        \
  57.                 }                                                                                    \
  58.                 else                                                                                \
  59.                 {                                                                                    \
  60.                     if ( fd >= 0 )                                                                \
  61.                     {                                                                                \
  62.                         odp->nextb = sp ;                                                        \
  63.                         if ( __sio_writef( odp, fd ) != bep - odp->start )            \
  64.                             return( ( cc != 0 ) ? cc : SIO_ERR ) ;                        \
  65.                         sp = odp->nextb ;                                                        \
  66.                         *sp++ = c ;                                                                \
  67.                         cc++ ;                                                                    \
  68.                     }                                                                                \
  69.                 }                                                                                    \
  70.                 if ( __SIO_MUST_FLUSH( *odp, c ) && fd >= 0 )                         \
  71.                 {                                                                                    \
  72.                     int b_in_buffer = sp - odp->start ;                                    \
  73.                                                                                                     \
  74.                     odp->nextb = sp ;                                                            \
  75.                     if ( __sio_writef( odp, fd ) != b_in_buffer )                    \
  76.                         return( cc ) ;                                                            \
  77.                     sp = odp->nextb ;                                                            \
  78.                 }                                                                                    \
  79.             }
  80.  
  81.  
  82.  
  83. #define NUM( c )            ( c - '0' )
  84.  
  85. #define STR_TO_DEC( str, num )                                    \
  86.                                     num = NUM( *str++ ) ;            \
  87.                                     while ( isdigit( *str ) )        \
  88.                                     {                                        \
  89.                                         num *= 10 ;                        \
  90.                                         num += NUM( *str++ ) ;        \
  91.                                     }
  92.  
  93. /*
  94.  * This macro does zero padding so that the precision
  95.  * requirement is satisfied. The padding is done by
  96.  * adding '0's to the left of the string that is going
  97.  * to be printed.
  98.  */
  99. #define FIX_PRECISION( adjust, precision, s, s_len )                \
  100.                     if ( adjust )                                                \
  101.                         while ( s_len < precision )                        \
  102.                         {                                                            \
  103.                             *--s = '0' ;                                        \
  104.                             s_len++ ;                                            \
  105.                         }
  106.  
  107. /*
  108.  * Macro that does padding. The padding is done by printing
  109.  * the character ch.
  110.  */
  111. #define PAD( width, len, ch )            do                                                        \
  112.                                                 {                                                        \
  113.                                                     INS_CHAR( ch, sp, bep, odp, cc, fd ) ;    \
  114.                                                     width-- ;                                        \
  115.                                                 }                                                        \
  116.                                                 while ( width > len )
  117.  
  118. /*
  119.  * Prefix the character ch to the string str
  120.  * Increase length
  121.  * Set the has_prefix flag
  122.  */
  123. #define PREFIX( str, length, ch )    *--str = ch ; length++ ; has_prefix = YES
  124.  
  125. #if defined(linux) || defined(BSD)
  126. PRIVATE char *conv_10( register wide_int num , register bool_int is_unsigned ,
  127.     register bool_int *is_negative , char *buf_end , register int *len ) ;
  128. #endif
  129.  
  130. /*
  131.  * Sprint is the equivalent of printf for SIO.
  132.  * It returns the # of chars written
  133.  * Assumptions:
  134.  *     - all floating point arguments are passed as doubles
  135.  */
  136. /* VARARGS2 */
  137. int Sprint( fd, fmt, va_alist ) 
  138.     int fd ;
  139.     register char *fmt ;
  140.     va_dcl
  141. {
  142.     __sio_descriptor_t *dp = &__sio_descriptors[ fd ] ;
  143.     register __sio_od_t *odp = ODP( dp ) ;
  144.     register int cc ;
  145.     va_list ap ;
  146.  
  147.     IO_SETUP( fd, dp, __SIO_OUTPUT_STREAM, SIO_ERR ) ;
  148.  
  149.     va_start( ap ) ;
  150.     cc = __sio_converter( odp, fd, fmt, ap ) ;
  151.     va_end( ap ) ;
  152.     return( cc ) ;
  153. }
  154.  
  155.  
  156. /*
  157.  * This is the equivalent of vfprintf for SIO
  158.  */
  159. int Sprintv( fd, fmt, ap )
  160.     int fd ;
  161.     char *fmt ;
  162.     va_list ap ;
  163. {
  164.     __sio_descriptor_t *dp = &__sio_descriptors[ fd ] ;
  165.     register __sio_od_t *odp = ODP( dp ) ;
  166.  
  167.     IO_SETUP( fd, dp, __SIO_OUTPUT_STREAM, SIO_ERR ) ;
  168.     return( __sio_converter( odp, fd, fmt, ap ) ) ;
  169. }
  170.  
  171.  
  172. /*
  173.  * Convert a floating point number to a string formats 'f', 'e' or 'E'.
  174.  * The result is placed in buf, and len denotes the length of the string
  175.  * The sign is returned in the is_negative argument (and is not placed
  176.  * in buf).
  177.  */
  178. PRIVATE char *conv_fp( format, num, add_dp, precision, is_negative, buf, len )
  179.     register char format ;
  180.     register double num ;
  181.     boolean_e add_dp ;            /* always add decimal point if YES */
  182.     int precision ;
  183.     bool_int *is_negative ;
  184.     char buf[] ;
  185.     int *len ;
  186. {
  187.     register char *s = buf ;
  188.     register char *p ;
  189.     int decimal_point ;
  190.     char *ecvt(), *fcvt() ;
  191.     char *conv_10() ;
  192.     char *strcpy() ;
  193.         
  194.     if ( format == 'f' )
  195.         p = fcvt( num, precision, &decimal_point, is_negative ) ;
  196.     else /* either e or E format */
  197.         p = ecvt( num, precision+1, &decimal_point, is_negative ) ;
  198.  
  199.     /*
  200.      * Check for Infinity and NaN
  201.      */
  202.     if ( isalpha( *p ) )
  203.     {
  204.         *len = strlen( strcpy( buf, p ) ) ;
  205.         *is_negative = FALSE ;
  206.         return( buf ) ;
  207.     }
  208.     
  209.     if ( format == 'f' )
  210.         if ( decimal_point <= 0 )
  211.         {
  212.             *s++ = '0' ;
  213.             if ( precision > 0 )
  214.             {
  215.                 *s++ = '.' ;
  216.                 while ( decimal_point++ < 0 )
  217.                     *s++ = '0' ;
  218.             }
  219.             else if ( add_dp )
  220.                 *s++ = '.' ;
  221.         }
  222.         else
  223.         {
  224.             while ( decimal_point-- > 0 )
  225.                 *s++ = *p++ ;
  226.             if ( precision > 0 || add_dp ) *s++ = '.' ;
  227.         }
  228.     else
  229.     {
  230.         *s++ = *p++ ;
  231.         if ( precision > 0 || add_dp ) *s++ = '.' ;
  232.     }
  233.  
  234.     /*
  235.      * copy the rest of p, the NUL is NOT copied
  236.      */
  237.     while ( *p ) *s++ = *p++ ;            
  238.     
  239.     if ( format != 'f' )
  240.     {
  241.         char temp[ EXPONENT_LENGTH ] ;                /* for exponent conversion */
  242.         int t_len ;
  243.         bool_int exponent_is_negative ;
  244.  
  245.         *s++ = format ;        /* either e or E */
  246.         decimal_point-- ;
  247.         if ( decimal_point != 0 )
  248.         {
  249.             p = conv_10( (wide_int)decimal_point, FALSE, &exponent_is_negative,
  250.                                                 &temp[ EXPONENT_LENGTH ], &t_len ) ;
  251.             *s++ = exponent_is_negative ? '-' : '+' ;
  252.             
  253.             /*
  254.              * Make sure the exponent has at least 2 digits
  255.              */
  256.             if ( t_len == 1 )
  257.                 *s++ = '0' ;
  258.             while ( t_len-- ) *s++ = *p++ ;
  259.         }
  260.         else
  261.         {
  262.             *s++ = '+' ;
  263.             *s++ = '0' ;
  264.             *s++ = '0' ;
  265.         }
  266.     }
  267.  
  268.     *len = s - buf ;
  269.     return( buf ) ;
  270. }
  271.  
  272.  
  273. /*
  274.  * Convert num to a base X number where X is a power of 2. nbits determines X.
  275.  * For example, if nbits is 3, we do base 8 conversion
  276.  * Return value:
  277.  *            a pointer to a string containing the number
  278.  *
  279.  * The caller provides a buffer for the string: that is the buf_end argument
  280.  * which is a pointer to the END of the buffer + 1 (i.e. if the buffer
  281.  * is declared as buf[ 100 ], buf_end should be &buf[ 100 ])
  282.  */
  283. PRIVATE char *conv_p2( num, nbits, format, buf_end, len )
  284.     register u_wide_int num ;
  285.     register int nbits ;
  286.     char format ;
  287.     char *buf_end ;
  288.     register int *len ;
  289. {
  290.     register int mask = ( 1 << nbits ) - 1 ;
  291.     register char *p = buf_end ;
  292.     static char low_digits[] = "0123456789abcdef" ;
  293.     static char upper_digits[] = "0123456789ABCDEF" ;
  294.     register char *digits = ( format == 'X' ) ? upper_digits : low_digits ;
  295.  
  296.     do
  297.     {
  298.         *--p = digits[ num & mask ] ;
  299.         num >>= nbits ;
  300.     }
  301.     while( num ) ;
  302.  
  303.     *len = buf_end - p ;
  304.     return( p ) ;
  305. }
  306.  
  307.  
  308.  
  309. /*
  310.  * Convert num to its decimal format.
  311.  * Return value:
  312.  *       - a pointer to a string containing the number (no sign)
  313.  *            - len contains the length of the string
  314.  *            - is_negative is set to TRUE or FALSE depending on the sign
  315.  *              of the number (always set to FALSE if is_unsigned is TRUE)
  316.  *
  317.  * The caller provides a buffer for the string: that is the buf_end argument
  318.  * which is a pointer to the END of the buffer + 1 (i.e. if the buffer
  319.  * is declared as buf[ 100 ], buf_end should be &buf[ 100 ])
  320.  */
  321. PRIVATE char *conv_10( num, is_unsigned, is_negative, buf_end, len )
  322.     register wide_int num ; 
  323.     register bool_int is_unsigned ;
  324.     register bool_int *is_negative ;
  325.     char *buf_end ;
  326.     register int *len ;
  327. {
  328.     register char *p = buf_end ;
  329.     register u_wide_int magnitude ;
  330.  
  331.     if ( is_unsigned )
  332.     {
  333.         magnitude = (u_wide_int) num ;
  334.         *is_negative = FALSE ;
  335.     }
  336.     else
  337.     {
  338.         *is_negative = ( num < 0 ) ;
  339.  
  340.         /*
  341.          * On a 2's complement machine, negating the most negative integer 
  342.          * results in a number that cannot be represented as a signed integer.
  343.          * Here is what we do to obtain the number's magnitude:
  344.          *        a. add 1 to the number
  345.          *        b. negate it (becomes positive)
  346.          *        c. convert it to unsigned
  347.          *        d. add 1
  348.          */
  349.         if ( *is_negative )
  350.         {
  351.             wide_int t = num + 1 ;
  352.  
  353.             magnitude = ( (u_wide_int) -t ) + 1 ;
  354.         }
  355.         else
  356.             magnitude = (u_wide_int) num ;
  357.     }
  358.  
  359.     /*
  360.      * We use a do-while loop so that we write at least 1 digit 
  361.      */
  362.     do
  363.     {
  364.         register u_wide_int new_magnitude = magnitude / 10 ;
  365.  
  366.         *--p = magnitude - new_magnitude*10 + '0' ;
  367.         magnitude = new_magnitude ;
  368.     }
  369.     while ( magnitude ) ;
  370.     
  371.     *len = buf_end - p ;
  372.     return( p ) ;
  373. }
  374.  
  375.  
  376. /*
  377.  * Do format conversion placing the output in odp
  378.  */
  379. int __sio_converter( odp, fd, fmt, ap )
  380.     register __sio_od_t *odp ;
  381.     int fd ;
  382.     register char *fmt ;
  383.     va_list ap ;
  384. {
  385.     register char *sp ;
  386.     register char *bep ;
  387.     register int cc = 0 ;
  388.     register int i ;
  389.  
  390.     register char *s ;
  391.     char *q ;
  392.     int s_len ;
  393.  
  394.     register int min_width ;
  395.     int precision ;
  396.     enum { LEFT, RIGHT } adjust ;
  397.     char pad_char ;
  398.     char prefix_char ;
  399.  
  400.     double fp_num ;
  401.     wide_int i_num ;
  402.     u_wide_int ui_num ;
  403.  
  404.     char num_buf[ NUM_BUF_SIZE ] ;
  405.     char char_buf[ 2 ] ;        /* for printing %% and %<unknown> */
  406.  
  407.     /*
  408.      * Flag variables
  409.      */
  410.     boolean_e is_long ;
  411.     boolean_e alternate_form ;
  412.     boolean_e print_sign ;
  413.     boolean_e print_blank ;
  414.     boolean_e adjust_precision ;
  415.     boolean_e adjust_width ;
  416.     bool_int is_negative ;
  417.  
  418.     char *conv_10(), *conv_p2(), *conv_fp() ;
  419.     char *gcvt() ;
  420.     char *strchr() ;
  421.  
  422.  
  423.     sp = odp->nextb ;
  424.     bep = odp->buf_end ;
  425.  
  426.     while ( *fmt )
  427.     {
  428.         if ( *fmt != '%' )
  429.         {
  430.             INS_CHAR( *fmt, sp, bep, odp, cc, fd ) ;
  431.         }
  432.         else
  433.         {
  434.             /*
  435.              * Default variable settings
  436.              */
  437.             adjust = RIGHT ;
  438.             alternate_form = print_sign = print_blank = NO ;
  439.             pad_char = ' ' ;
  440.             prefix_char = NUL ;
  441.  
  442.             fmt++ ;
  443.  
  444.             /*
  445.              * Try to avoid checking for flags, width or precision
  446.              */
  447.             if ( isascii( *fmt ) && ! islower( *fmt ) )
  448.             {
  449.                 /*
  450.                  * Recognize flags: -, #, BLANK, +
  451.                  */
  452.                 for ( ;; fmt++ )
  453.                 {
  454.                     if ( *fmt == '-' )
  455.                         adjust = LEFT ;
  456.                     else if ( *fmt == '+' )
  457.                         print_sign = YES ;
  458.                     else if ( *fmt == '#' )
  459.                         alternate_form = YES ;
  460.                     else if ( *fmt == ' ' )
  461.                         print_blank = YES ;
  462.                     else if ( *fmt == '0' )
  463.                         pad_char = '0' ;
  464.                     else
  465.                         break ;
  466.                 }
  467.  
  468.                 /*
  469.                  * Check if a width was specified
  470.                  */
  471.                 if ( isdigit( *fmt ) )
  472.                 {
  473.                     STR_TO_DEC( fmt, min_width ) ;
  474.                     adjust_width = YES ;
  475.                 }
  476.                 else if ( *fmt == '*' )
  477.                 {
  478.                     min_width = va_arg( ap, int ) ;
  479.                     fmt++ ;
  480.                     adjust_width = YES ;
  481.                     if ( min_width < 0 )
  482.                     {
  483.                         adjust = LEFT ;
  484.                         min_width = -min_width ;
  485.                     }
  486.                 }
  487.                 else
  488.                     adjust_width = NO ;
  489.                 
  490.                 /*
  491.                  * Check if a precision was specified
  492.                  *
  493.                  * XXX: an unreasonable amount of precision may be specified
  494.                  *          resulting in overflow of num_buf. Currently we
  495.                  *          ignore this possibility.
  496.                  */
  497.                 if ( *fmt == '.' )
  498.                 {
  499.                     adjust_precision = YES ;
  500.                     fmt++ ;
  501.                     if ( isdigit( *fmt ) )
  502.                     {
  503.                         STR_TO_DEC( fmt, precision ) ;
  504.                     }
  505.                     else if ( *fmt == '*' )
  506.                     {
  507.                         precision = va_arg( ap, int ) ;
  508.                         fmt++ ;
  509.                         if ( precision < 0 )
  510.                             precision = 0 ;
  511.                     }
  512.                     else
  513.                         precision = 0 ;
  514.                 }
  515.                 else
  516.                     adjust_precision = NO ;
  517.             }
  518.             else
  519.                 adjust_precision = adjust_width = NO ;
  520.  
  521.             /*
  522.              * Modifier check
  523.              */
  524.             if ( *fmt == 'l' )
  525.             {
  526.                 is_long = YES ;
  527.                 fmt++ ;
  528.             }
  529.             else
  530.                 is_long = NO ;
  531.  
  532.             /*
  533.              * Argument extraction and printing.
  534.              * First we determine the argument type.
  535.              * Then, we convert the argument to a string.
  536.              * On exit from the switch, s points to the string that
  537.              * must be printed, s_len has the length of the string
  538.              * The precision requirements, if any, are reflected in s_len.
  539.              *
  540.              * NOTE: pad_char may be set to '0' because of the 0 flag.
  541.              *            It is reset to ' ' by non-numeric formats
  542.              */
  543.             switch( *fmt )
  544.             {
  545.                 case 'd':
  546.                 case 'i':
  547.                 case 'u':
  548.                     if ( is_long )
  549.                         i_num = va_arg( ap, wide_int ) ;
  550.                     else
  551.                         i_num = (wide_int) va_arg( ap, int ) ;
  552.                     s = conv_10( i_num, (*fmt) == 'u', &is_negative,
  553.                                                 &num_buf[ NUM_BUF_SIZE ], &s_len ) ;
  554.                     FIX_PRECISION( adjust_precision, precision, s, s_len ) ;
  555.  
  556.                     if ( *fmt != 'u' )
  557.                     {
  558.                         if ( is_negative )
  559.                             prefix_char = '-' ;
  560.                         else if ( print_sign )
  561.                             prefix_char = '+' ;
  562.                         else if ( print_blank )
  563.                             prefix_char = ' ' ;
  564.                     }
  565.                     break ;
  566.                 
  567.  
  568.                 case 'o':
  569.                     if ( is_long )
  570.                         ui_num = va_arg( ap, u_wide_int ) ; 
  571.                     else
  572.                         ui_num = (u_wide_int) va_arg( ap, unsigned int ) ;
  573.                     s = conv_p2( ui_num, 3, *fmt, 
  574.                                                 &num_buf[ NUM_BUF_SIZE ], &s_len ) ;
  575.                     FIX_PRECISION( adjust_precision, precision, s, s_len ) ;
  576.                     if ( alternate_form && *s != '0' )
  577.                     {
  578.                         *--s = '0' ;
  579.                         s_len++ ;
  580.                     }
  581.                     break ;
  582.                 
  583.  
  584.                 case 'x':
  585.                 case 'X':
  586.                     if ( is_long )
  587.                         ui_num = (u_wide_int) va_arg( ap, u_wide_int ) ;
  588.                     else
  589.                         ui_num = (u_wide_int) va_arg( ap, unsigned int ) ;
  590.                     s = conv_p2( ui_num, 4, *fmt,
  591.                                                 &num_buf[ NUM_BUF_SIZE ], &s_len ) ;
  592.                     FIX_PRECISION( adjust_precision, precision, s, s_len ) ;
  593.                     if ( alternate_form && i_num != 0 )
  594.                     {
  595.                         *--s = *fmt ;            /* 'x' or 'X' */
  596.                         *--s = '0' ;
  597.                         s_len += 2 ;
  598.                     }
  599.                     break ;
  600.                 
  601.  
  602.                 case 's':
  603.                     s = va_arg( ap, char * ) ;
  604.                     if ( s != NULL )
  605.                     {
  606.                         s_len = strlen( s ) ;
  607.                         if ( adjust_precision && precision < s_len )
  608.                             s_len = precision ;
  609.                     }
  610.                     else
  611.                     {
  612.                         s = S_NULL ;
  613.                         s_len = S_NULL_LEN ;
  614.                     }
  615.                     pad_char = ' ' ;
  616.                     break ;
  617.                 
  618.  
  619.                 case 'f':
  620.                 case 'e':
  621.                 case 'E':
  622.                     fp_num = va_arg( ap, double ) ;
  623.  
  624.                     s = conv_fp( *fmt, fp_num, alternate_form,
  625.                             ( adjust_precision == NO ) ? FLOAT_DIGITS : precision,
  626.                                                     &is_negative, &num_buf[ 1 ], &s_len ) ;
  627.                     if ( is_negative )
  628.                         prefix_char = '-' ;
  629.                     else if ( print_sign )
  630.                         prefix_char = '+' ;
  631.                     else if ( print_blank )
  632.                         prefix_char = ' ' ;
  633.                     break ;
  634.  
  635.  
  636.                 case 'g':
  637.                 case 'G':
  638.                     if ( adjust_precision == NO )
  639.                         precision = FLOAT_DIGITS ;
  640.                     else if ( precision == 0 )
  641.                         precision = 1 ;
  642.                     /*
  643.                      * We use &num_buf[ 1 ], so that we have room for the sign
  644.                      */
  645.                     s = gcvt( va_arg( ap, double ), precision, &num_buf[ 1 ] ) ;
  646.                     if ( *s == '-' )
  647.                         prefix_char = *s++ ;
  648.                     else if ( print_sign )
  649.                         prefix_char = '+' ;
  650.                     else if ( print_blank )
  651.                         prefix_char = ' ' ;
  652.  
  653.                     s_len = strlen( s ) ;
  654.  
  655.                     if ( alternate_form && ( q = strchr( s, '.' ) ) == NULL )
  656.                         s[ s_len++ ] = '.' ;
  657.                     if ( *fmt == 'G' && ( q = strchr( s, 'e' ) ) != NULL )
  658.                         *q = 'E' ;
  659.                     break ;
  660.  
  661.  
  662.                 case 'c':
  663.                     char_buf[ 0 ] = (char) (va_arg( ap, int )) ;
  664.                     s = &char_buf[ 0 ] ;
  665.                     s_len = 1 ;
  666.                     pad_char = ' ' ;
  667.                     break ;
  668.  
  669.  
  670.                 case '%':
  671.                     char_buf[ 0 ] = '%' ;
  672.                     s = &char_buf[ 0 ] ;
  673.                     s_len = 1 ;
  674.                     pad_char = ' ' ;
  675.                     break ;
  676.  
  677.  
  678.                 case 'n':
  679.                     *(va_arg( ap, int * )) = cc ;
  680.                     break ;
  681.  
  682.                 /*
  683.                  * Always extract the argument as a "char *" pointer. We 
  684.                  * should be using "void *" but there are still machines 
  685.                  * that don't understand it.
  686.                  * If the pointer size is equal to the size of an unsigned
  687.                  * integer we convert the pointer to a hex number, otherwise 
  688.                  * we print "%p" to indicate that we don't handle "%p".
  689.                  */
  690.                 case 'p':
  691.                     ui_num = (u_wide_int) va_arg( ap, char * ) ;
  692.  
  693.                     if ( sizeof( char * ) <= sizeof( u_wide_int ) )
  694.                         s = conv_p2( ui_num, 4, 'x', 
  695.                                                 &num_buf[ NUM_BUF_SIZE ], &s_len ) ;
  696.                     else
  697.                     {
  698.                         s = "%p" ;
  699.                         s_len = 2 ;
  700.                     }
  701.                     pad_char = ' ' ;
  702.                     break ;
  703.                     
  704.  
  705.                 case NUL:
  706.                     /*
  707.                      * The last character of the format string was %.
  708.                      * We ignore it.
  709.                      */
  710.                     continue ;
  711.  
  712.  
  713.                     /*
  714.                       * The default case is for unrecognized %'s.
  715.                      * We print %<char> to help the user identify what
  716.                      * option is not understood.
  717.                      * This is also useful in case the user wants to pass
  718.                      * the output of __sio_converter to another function
  719.                      * that understands some other %<char> (like syslog).
  720.                      * Note that we can't point s inside fmt because the
  721.                      * unknown <char> could be preceded by width etc.
  722.                      */
  723.                 default:
  724.                     char_buf[ 0 ] = '%' ;
  725.                     char_buf[ 1 ] = *fmt ;
  726.                     s = char_buf ;
  727.                     s_len = 2 ;
  728.                     pad_char = ' ' ;
  729.                     break ;
  730.             }
  731.  
  732.             if ( prefix_char != NUL )
  733.             {
  734.                 *--s = prefix_char ;
  735.                 s_len++ ;
  736.             }
  737.  
  738.             if ( adjust_width && adjust == RIGHT && min_width > s_len )
  739.             {
  740.                 if ( pad_char == '0' && prefix_char != NUL )
  741.                 {
  742.                     INS_CHAR( *s, sp, bep, odp, cc, fd )
  743.                     s++ ;
  744.                     s_len-- ;
  745.                     min_width-- ;
  746.                 }
  747.                 PAD( min_width, s_len, pad_char ) ;
  748.             }
  749.  
  750.             /*
  751.              * Print the string s. 
  752.              */
  753.             for ( i = s_len ; i != 0 ; i-- )
  754.             {
  755.                 INS_CHAR( *s, sp, bep, odp, cc, fd ) ;
  756.                 s++ ;
  757.             }
  758.  
  759.             if ( adjust_width && adjust == LEFT && min_width > s_len )
  760.                 PAD( min_width, s_len, pad_char ) ;
  761.         }
  762.         fmt++ ;
  763.     }
  764.     odp->nextb = sp ;
  765.     return( cc ) ;
  766. }
  767.  
  768.